package cn.buk.qms.web;

import cn.buk.api.wechat.entity.WeixinEntConfig;
import cn.buk.api.wechat.work.dto.AppChatCreateRequest;
import cn.buk.api.wechat.work.dto.UserDetailResponse;
import cn.buk.api.wechat.work.dto.UserInfoResponse;
import cn.buk.api.wechat.work.dto.WorkWxData;
import cn.buk.api.wechat.work.message.AppChatTextMessage;
import cn.buk.api.wechat.work.service.WorkWeixinService;
import cn.buk.common.JsonResult;
import cn.buk.common.dto.CommonDto;
import cn.buk.common.sc.Page;
import cn.buk.tms.entity.misc.TmsWwAppChat;
import cn.buk.tms.entity.misc.TmsWwUser;
import cn.buk.tms.entity.misc.User;
import cn.buk.qms.service.EnterpriseService;
import cn.buk.qms.service.UserService;
import cn.buk.common.util.VerifyCodeUtil;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;

import static cn.buk.qms.HttpServletUtil.sendResponse;
import static cn.buk.qms.session.LoginUtil.execLoginProcess;

/**
 * 企业微信
 * @author yfdai
 */
@RestController
@RequestMapping("/ww")
public class WorkWxController extends BaseController {

  private static final Logger logger = LogManager.getLogger(WorkWxController.class);

  @Autowired
  private WorkWeixinService wwService;

  @Autowired
  private UserService userService;

  @Autowired
  private AuthenticationManager authenticationManager;

  @Autowired
  private EnterpriseService enterpriseService;

  @RequestMapping("/user")
  public UserDetailResponse getUserDetailByCode(HttpServletRequest request,
      @RequestParam("code") String code,
      @RequestParam("state") String state
  ) {
    UserDetailResponse r = null;

    logger.info("code: " + code + ", state: " + state);

    // "ww_123: 123表示企业ID"
    final int enterpriseId = Integer.parseInt(state.substring(3));
    UserInfoResponse o = wwService.getUserInfo(enterpriseId, code);
    if (o.getErrcode() == 0) {
      r = new UserDetailResponse();
      r.setUserid(o.getUserId());

      // 查找绑定的用户，然后自动登录
      User u = userService.getUserByWwUserId(enterpriseId, r.getUserid());
      if (u != null) {
        // 自动登录
        try {
          final String savePwd =
              u.getMd5Password() == null ? VerifyCodeUtil.MD5(u.getPassword()) : u.getMd5Password();

          execLoginProcess(authenticationManager, request.getSession(), u.getId(),
              u.getEnterprise().getId(), u.getUsername(), savePwd, u.getEmpname());
          logger.info("Auto login by userid: " + r.getUserid());
          //userService.sendAlert(enterpriseId, u.getUsername(), u.getEmpname() + "(用户名: " + u.getUsername() + ", " + "企业微信ID: " + r.getUserid() + ")自动登录.");
        } catch (AuthenticationException ex) {
          logger.error(ex.getMessage());
        }
      }
    } else {
      logger.warn(o.getErrcode() + ": " + o.getErrmsg());
      r = new UserDetailResponse();
    }

    return r;
  }

  /**
   * 接收企业微信发送过来的验证消息
   * @param request
   * @param enterpriseId
   * @param signature 企业微信加密签名，msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体
   * @param timestamp 时间戳
   * @param nonce 随机数
   * @param echostr 加密的字符串。需要解密得到消息内容明文，解密后有random、msg_len、msg、CorpID四个字段，其中msg即为消息内容明文
   */
  @GetMapping("/{id}/receive")
  public void workWechatVerify(HttpServletRequest request, HttpServletResponse response,
                                                @PathVariable("id") final int enterpriseId,
                               @RequestParam(value = "msg_signature") final String signature,
                               @RequestParam(value = "timestamp") final String timestamp,
                               @RequestParam(value = "nonce") final String nonce,
                               @RequestParam(value = "echostr", required = false) String echostr

  ) throws Exception {
    String msg = wwService.verifyWorkWeixinSource(enterpriseId, WeixinEntConfig.WORK_WX_DEFAULT, null, signature, timestamp, nonce, echostr);

    /**
     * 验证消息
     */
    if (msg != null && msg.length() > 0) {
      logger.debug(echostr);
      sendResponse(response, msg);
    }
  }

  @PostMapping("/{id}/receive")
  public String receiveWorkWechatMsg(HttpServletRequest request, HttpServletResponse response,
                               @PathVariable("id") final int enterpriseId,
                               @RequestParam(value = "msg_signature") final String signature,
                               @RequestParam(value = "timestamp") final String timestamp,
                               @RequestParam(value = "nonce") final String nonce

  ) throws Exception {
    final String requestXml = this.readInputXml(request);

    WorkWxData rq0 = WorkWxData.fromXml(requestXml);
    rq0.getToUserName();
    rq0.getAgentId();
    rq0.getEncryptedMsg();


    //解密后，获取明文内容
    String msg = wwService.verifyWorkWeixinSource(enterpriseId, WeixinEntConfig.WORK_WX_DEFAULT, null,
            signature, timestamp, nonce, rq0.getEncryptedMsg());

    logger.info(msg);

    WorkWxData rq = WorkWxData.fromXml(msg);


    if ("event".equalsIgnoreCase(rq.getMsgType())
            && "taskcard_click".equalsIgnoreCase(rq.getEvent())
    ) {
      userService.finishTaskCardMessage(enterpriseId, rq.getFromUserName(), rq.getTaskId(), rq.getEventKey(), rq.getCreateTime());
    }

    //返回接收成功
//    sendResponse(response, "success"); // 向微信服务器发送 success
    return "OK";
  }


  @GetMapping("/appChats")
  public CommonDto<TmsWwAppChat> searchAppChats(HttpServletRequest request) {
    final int enterpriseId = getEnterpriseId(request);

    List<TmsWwAppChat> menus = enterpriseService.searchWwAppChats(enterpriseId);

    CommonDto<TmsWwAppChat> dto = new CommonDto<>();
    dto.setDataList(menus);
    dto.setPage(new Page());

    return dto;
  }

  @GetMapping("/users")
  public CommonDto<TmsWwUser> searchUsers(HttpServletRequest request) {
    final int enterpriseId = getEnterpriseId(request);

    List<TmsWwUser> menus = enterpriseService.searchWwUsers(enterpriseId);

    CommonDto<TmsWwUser> dto = new CommonDto<>();
    dto.setDataList(menus);
    dto.setPage(new Page());

    return dto;
  }

  @PostMapping("/appChat")
  public JsonResult createAppChat(HttpServletRequest request,
                                  @RequestParam("name") String name,
                                  @RequestParam(value = "users[]") String[] users) {
    final int enterpriseId = getEnterpriseId(request);


    AppChatCreateRequest rq = new AppChatCreateRequest();
    rq.setName(name);
    rq.setUserList(Arrays.asList(users));

    var rs = wwService.createAppChat(enterpriseId, rq);
    if (rs.getErrcode() == 0) {
      //create success
      TmsWwAppChat appChat = new TmsWwAppChat();
      appChat.setName(name);
      appChat.setChatId(rs.getChatId());
      return enterpriseService.createWwAppChat(enterpriseId, appChat);

    } else {
      return JsonResult.createJsonResult(-1, rs.getErrmsg());
    }

  }

  @GetMapping("/appChat")
  public TmsWwAppChat searchAppChat(HttpServletRequest request,
                                               @RequestParam("chatId") String chatId) {
    final int enterpriseId = getEnterpriseId(request);

    return enterpriseService.searchWwAppChat(enterpriseId, chatId);
  }

  @PostMapping("/sendAppChat")
  public JsonResult sendAppChat(HttpServletRequest request,
                                  @RequestParam("chatId") String chatId,
                                  @RequestParam("content") String content) {
    final int enterpriseId = getEnterpriseId(request);


    AppChatTextMessage rq = new AppChatTextMessage();
    rq.setChatId(chatId);
    rq.getText().setContent(content);

    var rs = wwService.sendAppChat(enterpriseId, rq);
    if (rs.getErrcode() == 0) {
      //create success
      return JsonResult.createJsonResult(1, "发送成功");

    } else {
      return JsonResult.createJsonResult(-1, rs.getErrmsg());
    }

  }
}
